#include <sys/epoll.h>
#include "mytcp.h"

/*========================================<网络地址类>========================================*/
InetAddress::InetAddress()
{
    bzero(&addr, sizeof(addr));
    addr_len = sizeof(addr);
}

InetAddress::InetAddress(const char* ip, uint16_t port)
{
    this->addr.sin_family = AF_INET;
    this->addr.sin_port = htons(port);
    inet_pton(AF_INET, ip, &this->addr.sin_addr);
    addr_len = sizeof(this->addr);
}

InetAddress::~InetAddress(){}


/*========================================<socket套接字类>========================================*/

Socket::Socket():fd(-1)
{
    this->fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0)
    {
        perror("socket");
        exit(EXIT_FAILURE);
    }
}

Socket::Socket(int fd) :fd(fd)
{
    if (fd < 0)
    {
        perror("socket");
        exit(EXIT_FAILURE);
    }
}

Socket::~Socket()
{
    if (this->fd != -1)
        close(this->fd);
    fd = -1;
}

int Socket::getFd()const { return this->fd; }

void Socket::setnonblocking()
{
    fcntl(this->fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
}

void Socket::bind(InetAddress* inetAddr)
{
    if (::bind(this->fd, (sockaddr*)&inetAddr->addr, inetAddr->addr_len) < 0)
    {
        perror("bind");
        exit(EXIT_FAILURE);
    }
}

void Socket::listen(int backLog)
{
    int ret;
    ret = ::listen(this->fd, backLog);
    if (ret < 0)
    {
        perror("listen");
        exit(EXIT_FAILURE);
    }
}

int Socket::accept(InetAddress* inetAddr)
{
    int clientFd = -1;
    clientFd = ::accept(this->fd, (sockaddr*)&inetAddr->addr, &inetAddr->addr_len);
    if (clientFd < 0)
    {
        perror("accept");
    }
    return clientFd;
}

/*========================================<epoll边缘触发类，IO多路复用>========================================*/

EpollET::EpollET() :epfd(-1)
{
    this->epfd = epoll_create1(0);
    if (epfd < 0) { perror("epoll_create1"); exit(1); }

    this->events = new struct epoll_event[MAX_EVENTS];
    bzero(events, sizeof(*events) * MAX_EVENTS);
}

EpollET::~EpollET()
{
    if (epfd != 0)
        close(epfd);

    delete[] events;
}

int EpollET::add_fd(int fd, uint32_t op)
{
    struct epoll_event ev;
    ev.data.fd = fd;
    ev.events = op;

    if (epoll_ctl(this->epfd, EPOLL_CTL_ADD, fd, &ev) < 0) { perror("epoll_ctl"); return -1; }
    return 0;
}

std::vector<epoll_event> EpollET::poll(int timeout)
{
    std::vector<epoll_event> activeEvents;
    int nfds;
    nfds = epoll_wait(this->epfd, this->events, MAX_EVENTS, timeout);
    if (nfds < 0)
    {
        perror("epoll_wait");
        exit(1);
    }

    for (int i = 0;i < nfds;i++)
    {
        activeEvents.push_back(events[i]);
    }
    return activeEvents;

}